﻿using Devil;
using UnityEditor;
using UnityEngine;

namespace GameToolkit.Editor
{
    [CustomPropertyDrawer(typeof(AssetPathAttribute))]
    [CustomPropertyDrawer(typeof(AssetAddress))]
    public class AssetPathDrawer : PropertyDrawer
    {
        string _path;
        Object _asset;

        void GetAsset(System.Type assetType, SerializedProperty pathprop, SerializedProperty guidprop)
        {
            string address;
            if (guidprop != null && !string.IsNullOrEmpty(guidprop.stringValue))
            {
                address = AssetDatabase.GUIDToAssetPath(guidprop.stringValue);
            }
            else
            {
                address = pathprop.stringValue;
            }
            if (_asset == null || address != _path)
            {
                _asset = string.IsNullOrEmpty(address) ? null : AssetDatabase.LoadAssetAtPath(address, assetType);
                _path = address;
                if (guidprop != null)
                {
                    var guid = string.IsNullOrEmpty(address) ? "" : AssetDatabase.AssetPathToGUID(address);
                    if (guid != guidprop.stringValue)
                        guidprop.stringValue = guid;
                }
                if (pathprop.stringValue != address)
                    pathprop.stringValue = address;
                //prop.stringValue = asset == null ? "" : GetRelativePath(att.AssetFolder, path);
            }
        }

        public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
        {
            var isAddress = property.type == "AssetAddress";
            if (!isAddress && property.propertyType != SerializedPropertyType.String)
                return 40;
            return base.GetPropertyHeight(property, label);
        }

        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            var isAddress = property.type == "AssetAddress";
            if (!isAddress && property.propertyType != SerializedPropertyType.String)
            {
                EditorGUI.HelpBox(position, "AssetPathAttribute Only Support String or AssetAddress Type", MessageType.Warning);
                return;
            }

            SerializedProperty guid, path;
            if (isAddress)
            {
                guid = property.FindPropertyRelative("guid");
                path = property.FindPropertyRelative("path");
            }
            else
            {
                guid = null;
                path = property;
            }
            var att = attribute as AssetPathAttribute;
            //label.text = ParallelUtils.Concat(label.text, guid == null ? " (path)" : " (guid)");
            if (Application.isPlaying)
            {
                EditorGUI.BeginDisabledGroup(true);
                //base.OnGUI(position, property, label);
                EditorGUI.PropertyField(position, path, label);
                EditorGUI.EndDisabledGroup();
                return;
            }

            var assetType = att == null || att.AssetType == null ? typeof(GameObject) : att.AssetType;
            if (property.hasMultipleDifferentValues)
            {
                _asset = null;
                _path = "";
            }
            else
            {
                GetAsset(assetType, path, guid);
            }
            EditorGUI.BeginProperty(position, label, property);
            var lv = EditorGUI.indentLevel;
            var pos = EditorGUI.PrefixLabel(position, label);
            var w = isAddress ? Mathf.Max(pos.width * 0.5f, pos.width - 40) : pos.width;
            var vpos = new Rect(pos.x, pos.y, w, pos.height);
            EditorGUI.indentLevel = 0;
            var obj = EditorGUI.ObjectField(vpos, _asset, assetType, false);
            if (obj != _asset)
            {
                _asset = obj;
                var p = obj == null ? "" : AssetDatabase.GetAssetPath(obj);
                _path = p;
                path.stringValue = p;
                if (guid != null)
                    guid.stringValue = obj == null ? "" : AssetDatabase.AssetPathToGUID(p);
                GUI.changed = true;
            }
            if (isAddress)
            {
                vpos = new Rect(pos.x + w, pos.y, pos.width - w, pos.height);
                label.text = "sync";
                EditorGUI.BeginDisabledGroup(_path.EqualsIgnoreCase(path.stringValue));
                var syncpath = GUI.Button(vpos, label);
                EditorGUI.EndDisabledGroup();
                if (syncpath)
                {
                    string gid = guid.stringValue, gpath = guid.stringValue;
                    if (!string.IsNullOrEmpty(gid))
                    {
                        gpath = AssetDatabase.GUIDToAssetPath(gid);
                    }
                    else if (!string.IsNullOrEmpty(gpath))
                    {
                        gid = AssetDatabase.AssetPathToGUID(gpath);
                    }
                    GUI.changed = gpath != path.stringValue || gid != guid.stringValue;
                    path.stringValue = gpath;
                    guid.stringValue = gid;
                }
                var v = property.FindPropertyRelative("variant");
                var isVariant = AssetsUtil.VariantsForEditor.IsInitialized ? AssetsUtil.VariantsForEditor.GetVariantGroup(EVariantGroupQuery.AssetPath, path.stringValue) != null : v.boolValue;
                // MakeAB.AutoVariantsPattern != null && MakeAB.AutoVariantsPattern.IsMatch(path.stringValue);
                if(isVariant != v.boolValue)
                {
                    v.boolValue = isVariant;
                    GUI.changed = true;
                }
                //EditorGUI.SelectableLabel(vpos,
                //    showhash == EHashType.ToHash ? StringUtil.ToHash(path.stringValue).ToString()
                //    : StringUtil.IgnoreCaseToHash(path.stringValue).ToString(),
                //    DevilEditorUtility.HintStyle("label"));
            }
            EditorGUI.indentLevel = lv;
            EditorGUI.EndProperty();
        }
    }
}